package tp.pr5.instructions;


import tp.pr5.Constants;
import tp.pr5.NavigationModule;
import tp.pr5.RobotEngine;
import tp.pr5.instructions.exceptions.InstructionExecutionException;
import tp.pr5.instructions.exceptions.WrongInstructionFormatException;
import tp.pr5.items.Item;
import tp.pr5.items.ItemContainer;

/**
 * This instruction tries to pick an Item from the current place and puts it the robot inventory.
 * This instruction works if the user writes PICK id or COGER id
 *
 */
public class PickInstruction implements Instruction 
{
	
	private NavigationModule navigation;
	private ItemContainer robotContainer;
	private String id;
	private RobotEngine engine;

	/**
	 * Default constructor
	 */
	public PickInstruction()
	{
		this.robotContainer = null;
		this.navigation = null;
	}
	
	/**
	 * Constructor with id
	 * @param id of the item
	 */
	public PickInstruction(String id)
	{
		this();
		this.id = id;
	}

	/**
	 * Parses the String returning an instance of PickInstruction or throwing a WrongInstructionFormatException()
	 * 
	 * @param cad string given
	 */
	@Override
	public Instruction parse(String cad) throws WrongInstructionFormatException 
	{
		String[] entry = cad.trim().split(" +");
		if((entry[0].toUpperCase().equals("PICK") || entry[0].toUpperCase().equals("COGER")) && entry.length == 1)
		{
			throw new WrongInstructionFormatException(); 
		}
		if((entry[0].toUpperCase().equals("PICK") || entry[0].toUpperCase().equals("COGER")) && entry.length == 2)
		{
			return new PickInstruction(entry[1]);
		}
		throw new WrongInstructionFormatException();
	}

	/**
	 * Fixes the current context, i.e., the robot engine and the navigation module
	 * 
	 * @param engine RobotEngine
	 * @param navigation NavigationModule
	 * @param robotContainer ItemContainer
	 * 
	 */
	@Override
	public void configureContext(RobotEngine engine, NavigationModule navigation, ItemContainer robotContainer) 
	{
		this.navigation = navigation;
		this.robotContainer = robotContainer;
		this.engine = engine;
	}

	/**
	 * The robot adds an item to its inventory from the current place, if it exists
	 */
	@Override
	public void execute() throws InstructionExecutionException 
	{
		try
		{
			Item item = this.navigation.pickItemFromCurrentPlace(this.id);
			
	
			//Checks if the item exists
			if(item != null)
			{
				//Checks if the robot has the object already
				if(this.robotContainer.positionItem(this.id) == - 1)
				{
					if(item.canBeDefused())
					{
						int damage = item.explode();
						
						this.engine.addFuel(damage);
						this.engine.saySomething(Constants.MESSAGE_BOMB_EXPLODE.replace("{SCORE}", Integer.toString(-damage)));
					}
					else
					{
						this.robotContainer.addItem(item);
						this.engine.saySomething(Constants.MESSAGE_PICK_OK.replace("{ID}", this.id));
					}	
				}
				else 
				{
					this.navigation.dropItemAtCurrentPlace(item);
					throw new InstructionExecutionException(Constants.MESSAGE_ITEM_IS_IN_INVENTORY.replace("{ID}", this.id));
				}
			}
			else
			{
				throw new InstructionExecutionException(Constants.MESSAGE_PICK_ERROR1.replace("{ID}", this.id));
			}
		} catch(Exception e){
			throw e;
		}
	}

	/**
	 * Returns a description of the Instruction syntax. The string does not end with the line separator. It is up to the caller adding it before printing.
	 */
	@Override
	public String getHelp() 
	{
		return "PICK|COGER <id>";
	}

}
